package com.wujie.mall.domain.payment.impl;

import com.wujie.mall.domain.payment.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * 微信支付渠道实现
 * 
 * 设计模式应用：工厂方法模式的具体产品
 * 
 * @author wujie
 * @since 2024-08-26
 */
@Slf4j
@Component
public class WechatPayChannel implements PaymentChannel {

    private static final String WECHAT_API_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    
    @Override
    public PaymentResponse pay(PaymentRequest request) {
        log.info("开始处理微信支付，订单号: {}, 金额: {}", request.getOrderNo(), request.getAmount());
        
        try {
            // 验证请求参数
            validateRequest(request);
            
            // 模拟微信支付处理
            String paymentNo = generateWechatTradeNo(request.getOrderNo());
            String prepayId = generatePrepayId();
            
            // 构建微信支付参数
            String paymentData = buildWechatPayData(request, prepayId);
            
            log.info("微信支付预处理成功，支付单号: {}, 预支付ID: {}", paymentNo, prepayId);
            
            PaymentResponse response = PaymentResponse.success(request.getOrderNo(), paymentNo, paymentData);
            response.putExtraData("prepay_id", prepayId);
            response.putExtraData("package", "prepay_id=" + prepayId);
            
            return response;
            
        } catch (Exception e) {
            log.error("微信支付处理失败，订单号: {}", request.getOrderNo(), e);
            return PaymentResponse.failure(request.getOrderNo(), "WECHAT_ERROR", e.getMessage());
        }
    }

    @Override
    public PaymentResponse queryPaymentStatus(String orderNo) {
        log.info("查询微信支付状态，订单号: {}", orderNo);
        
        try {
            // 模拟查询微信支付状态
            Thread.sleep(80); // 模拟网络延迟
            
            // 模拟随机支付状态
            boolean isPaid = Math.random() > 0.4; // 60%概率支付成功
            
            if (isPaid) {
                String paymentNo = generateWechatTradeNo(orderNo);
                PaymentResponse response = PaymentResponse.success(orderNo, paymentNo, null);
                response.putExtraData("trade_state", "SUCCESS");
                response.putExtraData("time_end", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
                response.putExtraData("bank_type", "CMC"); // 模拟银行类型
                return response;
            } else {
                return PaymentResponse.pending(orderNo, generateWechatTradeNo(orderNo));
            }
            
        } catch (Exception e) {
            log.error("查询微信支付状态失败，订单号: {}", orderNo, e);
            return PaymentResponse.failure(orderNo, "QUERY_ERROR", e.getMessage());
        }
    }

    @Override
    public PaymentResponse cancelPayment(String orderNo) {
        log.info("取消微信支付，订单号: {}", orderNo);
        
        try {
            // 模拟取消微信支付
            Thread.sleep(60); // 模拟网络延迟
            
            PaymentResponse response = PaymentResponse.builder()
                    .success(true)
                    .status(PaymentResponse.PaymentStatus.CANCELLED)
                    .orderNo(orderNo)
                    .responseTime(LocalDateTime.now())
                    .build();
            
            response.putExtraData("recall_time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
            response.putExtraData("recall_result", "SUCCESS");
            
            log.info("微信支付取消成功，订单号: {}", orderNo);
            return response;
            
        } catch (Exception e) {
            log.error("取消微信支付失败，订单号: {}", orderNo, e);
            return PaymentResponse.failure(orderNo, "CANCEL_ERROR", e.getMessage());
        }
    }

    @Override
    public PaymentType getPaymentType() {
        return PaymentType.WECHAT_PAY;
    }

    /**
     * 生成微信交易号
     * @param orderNo 订单号
     * @return 微信交易号
     */
    private String generateWechatTradeNo(String orderNo) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 6);
        return "WX_" + timestamp + "_" + uuid;
    }

    /**
     * 生成预支付ID
     * @return 预支付ID
     */
    private String generatePrepayId() {
        return "prepay_id_" + UUID.randomUUID().toString().replace("-", "").substring(0, 16);
    }

    /**
     * 构建微信支付数据
     * @param request 支付请求
     * @param prepayId 预支付ID
     * @return 微信支付数据JSON
     */
    private String buildWechatPayData(PaymentRequest request, String prepayId) {
        // 在实际应用中，这里会根据微信支付SDK构建真实的支付参数
        StringBuilder data = new StringBuilder();
        data.append("{");
        data.append("\"appId\":\"wxd930ea5d5a258f4f\",");
        data.append("\"timeStamp\":\"").append(System.currentTimeMillis() / 1000).append("\",");
        data.append("\"nonceStr\":\"").append(UUID.randomUUID().toString().replace("-", "").substring(0, 16)).append("\",");
        data.append("\"package\":\"prepay_id=").append(prepayId).append("\",");
        data.append("\"signType\":\"MD5\",");
        data.append("\"paySign\":\"").append(generateSignature()).append("\"");
        data.append("}");
        
        return data.toString();
    }

    /**
     * 生成微信支付签名
     * @return 签名
     */
    private String generateSignature() {
        // 在实际应用中，这里会根据微信支付规则生成真实的签名
        return UUID.randomUUID().toString().replace("-", "").toUpperCase();
    }

    @Override
    public void validateRequest(PaymentRequest request) {
        PaymentChannel.super.validateRequest(request);
        
        // 微信支付特有的验证逻辑
        if (request.getBody() == null || request.getBody().trim().isEmpty()) {
            throw new IllegalArgumentException("微信支付必须提供商品描述");
        }
        
        if (request.getNotifyUrl() == null || request.getNotifyUrl().trim().isEmpty()) {
            throw new IllegalArgumentException("微信支付必须提供异步通知地址");
        }
        
        // 微信支付金额限制：单笔最小0.01元，最大10万元
        if (request.getAmount().compareTo(new java.math.BigDecimal("0.01")) < 0) {
            throw new IllegalArgumentException("微信支付金额不能小于0.01元");
        }
        
        if (request.getAmount().compareTo(new java.math.BigDecimal("100000")) > 0) {
            throw new IllegalArgumentException("微信支付金额不能超过10万元");
        }
        
        // 检查用户ID
        if (request.getUserId() == null) {
            throw new IllegalArgumentException("微信支付必须提供用户ID");
        }
        
        log.debug("微信支付请求验证通过，订单号: {}", request.getOrderNo());
    }
}